home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1992 by Panagiotis Tsirigotis
- * All rights reserved. The file named COPYRIGHT specifies the terms
- * and conditions for redistribution.
- */
-
- /*
- * $Id: fsma.c,v 5.1 1992/10/10 07:23:18 panos Exp $
- */
-
- #include "fsma.h"
- #include "impl.h"
-
- #ifdef DEBUG
- #include <stdio.h>
- #endif
-
- /*
- * We assume that memory handed by malloc is suitably aligned for any
- * machine data type (for example, if the CPU wants double's aligned
- * at an 8-byte boundary, the memory provided by malloc will be so aligned).
- */
- char *malloc() ;
- int free() ;
-
- static char *version = VERSION ;
-
- PRIVATE void init_free_list __ARGS( ( unsigned, unsigned, char * ) ) ;
- PRIVATE void terminate __ARGS( ( char * ) ) ;
-
-
- /*
- * An allocator manages a linked list of chunks:
- *
- * ______________ ______________ ______________
- * | HEADER |------>| |------>| |
- * |____________| |____________| |____________|
- * | | | | | |
- * | | | | | |
- * | | | | | |
- * | | | | | |
- * | SLOTS | | | | |
- * | | | | | |
- * | | | | | |
- * | | | | | |
- * | | | | | |
- * |____________| |____________| |____________|
- *
- *
- * The SLOTS sections are organized as a linked list of slots whose
- * size is determined by the object size specified in fsm_create
- */
-
- fsma_h fsm_create( object_size, slots_per_chunk, flags )
- unsigned object_size ;
- unsigned slots_per_chunk ;
- int flags ;
- {
- register fsma_h fp ;
- union __fsma_chunk_header *chp ;
- char *slots ;
- unsigned nslots ;
- unsigned chunk_size, slot_size ;
- int header_inlined ;
-
- slot_size = ( object_size < MINSIZE ) ? MINSIZE : object_size ;
- nslots = ( slots_per_chunk == 0 ) ? SLOTS_PER_CHUNK : slots_per_chunk ;
-
- chunk_size = sizeof( union __fsma_chunk_header ) + nslots * slot_size ;
-
- chp = CHUNK_HEADER( malloc( chunk_size ) ) ;
- if ( chp == NULL )
- if ( flags & FSM_RETURN_ERROR )
- return( NULL ) ;
- else
- terminate( "FSMA fsm_create: malloc failed\n" ) ;
-
- slots = (char *) &chp[ 1 ] ;
- init_free_list( nslots, slot_size, slots ) ;
-
- #ifdef DEBUG
- {
- int i ;
-
- fprintf( stderr, "Size = %d, nslots = %d\n", slot_size, nslots ) ;
- for ( i = 0 ; i < nslots+1 ; i++ )
- fprintf( stderr, "slot[ %d ] = %p\n",
- i, (*(char **) (slots + i * slot_size ))) ;
- }
- #endif
-
- /*
- * Check if we can fit the header in an object slot
- */
- if ( slot_size >= sizeof( struct __fsma_header ) )
- {
- /*
- * We can do it.
- * Allocate the first slot
- */
- fp = (fsma_h) slots ;
- slots = *(POINTER *) slots ;
- header_inlined = TRUE ;
- }
- else
- {
- fp = (fsma_h) malloc( sizeof( struct __fsma_header ) ) ;
- if ( fp == NULL )
- if ( flags & FSM_RETURN_ERROR )
- {
- free( (char *) chp ) ;
- return( NULL ) ;
- }
- else
- terminate( "FSMA fsm_create: malloc of header failed\n" ) ;
- header_inlined = FALSE ;
- }
-
- chp->next_chunk = NULL ;
-
- fp->next_free = (POINTER) slots ;
- fp->chunk_chain = chp ;
- fp->slots_in_chunk = nslots ;
- fp->slot_size = slot_size ;
- fp->chunk_size = chunk_size ;
- fp->flags = flags ;
- fp->is_inlined = header_inlined ;
-
- #ifdef DEBUG
- fprintf( stderr, "Slots/chunk = %d\n", nslots ) ;
- fprintf( stderr, "Allocating chunk %p\n", chunk ) ;
- #endif
-
- return( (fsma_h) fp ) ;
- }
-
-
-
- void fsm_destroy( fp )
- register fsma_h fp ;
- {
- int header_inlined = fp->is_inlined ;
- register union __fsma_chunk_header *chp, *next_chunk ;
- register int zero_memory = fp->flags & FSM_ZERO_DESTROY ;
- register chunk_size = fp->chunk_size ;
-
- /*
- * Free all chunks in the chunk chain
- */
- for ( chp = fp->chunk_chain ; chp != NULL ; chp = next_chunk )
- {
- next_chunk = chp->next_chunk ;
- if ( zero_memory )
- (void) memset( (char *)chp, 0, chunk_size ) ;
-
- #ifdef DEBUG
- fprintf( stderr, "Freeing chunk %p\n", chp ) ;
- #endif
- free( (char *)chp ) ;
- }
-
- /*
- * If fp->inlined is NO, we have to free the handle.
- * Note that we copied fp->inlined in case it is YES.
- */
- if ( ! header_inlined )
- free( (char *)fp ) ;
- }
-
-
- char *_fsm_alloc( fp )
- register fsma_h fp ;
- {
- register POINTER object ;
-
- /*
- * Check if there are any slots on the free list
- */
- if ( fp->next_free == NULL )
- {
- /*
- * Free list exhausted; allocate a new chunk
- */
- char *slots ;
- union __fsma_chunk_header *chp ;
-
- chp = CHUNK_HEADER( malloc( fp->chunk_size ) ) ;
- if ( chp == NULL )
- if ( fp->flags & FSM_RETURN_ERROR )
- return( NULL ) ;
- else
- terminate( "FSMA fsm_alloc: malloc failed\n" ) ;
-
- #ifdef DEBUG
- fprintf( stderr, "Allocating chunk %p\n", chunk ) ;
- #endif
- /*
- * Put the slots in this chunk in a linked list
- * and add this list to the free list
- */
- slots = (char *) &chp[ 1 ] ;
- init_free_list( fp->slots_in_chunk, fp->slot_size, slots ) ;
- fp->next_free = (POINTER) slots ;
-
- /*
- * Put this chunk at the head of the chunk chain
- */
- chp->next_chunk = fp->chunk_chain ;
- fp->chunk_chain = chp ;
- }
-
- object = fp->next_free ;
- fp->next_free = *(POINTER *)object ;
-
- if ( fp->flags & FSM_ZERO_ALLOC )
- (void) memset( object, 0, fp->slot_size ) ;
-
- return( object ) ;
- }
-
-
- void _fsm_free( fp, object )
- fsma_h fp ;
- char *object ;
- {
- if ( fp->flags & FSM_ZERO_FREE )
- (void) memset( object, 0, fp->slot_size ) ;
-
- *(POINTER *)object = fp->next_free ;
- fp->next_free = object ;
- }
-
-
- PRIVATE void terminate( s )
- char *s ;
- {
- write( 2, s, strlen( s ) ) ;
- abort() ;
- exit( 1 ) ;
- }
-
-
- PRIVATE void init_free_list( nslots, size, slots )
- unsigned nslots ;
- register unsigned size ;
- char *slots ;
- {
- register int i ;
- register char *next ;
- register POINTER current ;
-
- for ( i = 0, current = slots, next = slots + size ; i < nslots - 1 ;
- i++, current = next, next += size )
- *(POINTER *)current = next ;
- *(POINTER *)current = NULL ;
- }
-
-